package com.smedi.ismedi.web.starter.handler;//package com.smedi.ismedi.personnel.core.starter.handler;

import com.smedi.ismedi.authority.starter.common.ResponseData;
import com.smedi.ismedi.authority.starter.exception.BasicError;
import com.smedi.ismedi.authority.starter.exception.LogicException;
import com.smedi.ismedi.web.starter.property.ExceptionProperty;
import feign.RetryableException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.junit.platform.commons.util.ExceptionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.SocketTimeoutException;
import java.util.Arrays;

@Slf4j
@ControllerAdvice(annotations = RestController.class)
@RequiredArgsConstructor
public class GlobalExceptionHandler {
    private final Environment env;

    private final ExceptionProperty exceptionProperty;

    @Value("${spring.application.name}")
    private String application;

    private final String[] multiEnvs = new String[]{"local", "dev", "crp", "test"}; // 允许多端登录的环境

    private String getExceptionMessage(Exception e) {
        String active = env.getActiveProfiles()[0]; // 当前环境
        if (!Arrays.asList(multiEnvs).contains(active)) {
            return e.getMessage();
        } else {
            return exceptionProperty.isReturnTrace() ? ExceptionUtils.readStackTrace(e) : e.getMessage();
        }
    }

    /**
     * 自定义抛错的消息内容
     *
     * @param request
     * @param e
     * @param response
     * @return
     */
    @ExceptionHandler(value = LogicException.class)
    @ResponseBody
    @Order(1)
    public ResponseData<Void> logicExceptionHandler(HttpServletRequest request, LogicException e, HttpServletResponse response) throws Exception {
        log.error("LogicException message is: {}",
                e.getMessage(),
                e);
        //        if (exceptionProperty.isPrintTrace()) {
//            e.printStackTrace();
//
//        }
//        if (BasicError.TOKEN_INVALID.getCode().equals(e.getCode())) {
//            response.setStatus(HttpStatus.SC_UNAUTHORIZED);
//        }
        return new ResponseData<Void>().failure(application, e.getCode(), e.getErrorMsg(), getExceptionMessage(e));
    }

    /**
     * Validate 抛错的消息内容
     *
     * @param exception 异常
     * @return ResponseData<Void>
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseBody
    @Order(1)
    public ResponseData<Void> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException exception) {
        return new ResponseData<Void>().failure(application, BasicError.METHOD_ARGUMENT_NOT_VALID.getCode(), exception.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }

    /**
     * 绑定错误信息
     *
     * @param request
     * @param e
     * @param response
     * @return
     */
    @Order(1)
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public ResponseData<Void> BindExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e, HttpServletResponse response) {
        log.error("BindException message is: {}",
                e.getMessage(),
                e);
        //        if (exceptionProperty.isPrintTrace()) {
//            e.printStackTrace();
//
//        }
        return new ResponseData().failure(application, BasicError.UN_HANDLER_EXCEPTION.getCode(), getExceptionMessage(e));
    }

    /**
     * 绑定错误信息
     *
     * @param exception 异常
     */
    @Order(1)
    @ExceptionHandler(value = RetryableException.class)
    @ResponseBody
    public ResponseData<Void> RetryableExceptionHandler(RetryableException exception) {
        return new ResponseData<Void>().failure(application, BasicError.NET_FAILURE.getCode(), BasicError.NET_FAILURE.getMessage(), exception.getMessage());
    }

    /**
     * 绑定错误信息
     *
     * @param exception 异常
     */
    @Order(1)
    @ExceptionHandler(value = SocketTimeoutException.class)
    @ResponseBody
    public ResponseData<Void> SocketTimeoutExceptionHandler(SocketTimeoutException exception) {
        return new ResponseData<Void>().failure(application, BasicError.NET_FAILURE.getCode(), BasicError.NET_FAILURE.getMessage(), exception.getMessage());
    }

    /**
     * 其他抛错的消息内容
     *
     * @param request
     * @param e
     * @param response
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    @Order(2)
    public ResponseData<Void> unhandledExceptionHandler(HttpServletRequest request, Exception e, HttpServletResponse response) {
        log.error("Exception message is: {}",
                e.getMessage(),
                e);

        //        if (exceptionProperty.isPrintTrace()) {
//
//
//        };
        // 系统级异常，错误码固定为-1，提示语固定为系统繁忙，请稍后再试
//        Object value = request.getSession().getAttribute(AuthorityConstant.code401);
//        if (value != null) {
//            if (Boolean.valueOf(value.toString())) {
//                response.setStatus(HttpStatus.SC_UNAUTHORIZED);
//            }
//        }
        return new ResponseData<Void>().failure(application, BasicError.UNKNOWN_EXCEPTION.getCode(), getExceptionMessage(e));
    }
}
